package com.sscl.baselibrary.utils

import android.app.Activity
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import java.io.File
import java.io.PrintWriter
import java.util.concurrent.ThreadFactory
import androidx.core.net.toUri
import com.sscl.baselibrary.files.FileProviderUtil
import com.sscl.baselibrary.provider.AutoInitProvider


/**
 * @author jackie
 */
object ApkController {

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 接口定义
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    interface OnInstallResultListener {
        /**
         * 成功
         */
        fun succeed()

        /**
         * 失败
         */
        fun failed()
    }

    /* * * * * * * * * * * * * * * * * * * 属性声明 * * * * * * * * * * * * * * * * * * */

    private val TAG = ApkController::class.java.simpleName

    private val handler = Handler(Looper.getMainLooper())

    private val threadFactory = ThreadFactory { r -> Thread(r, "ApkController") }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 公开方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 描述: 安装
     */
    fun <T : Activity> install(
        apkPath: String,
        packageName: String,
        launcherActivity: Class<T>,
        context: Context,
        onInstallResultListener: OnInstallResultListener?
    ) {
        DebugUtil.warnOut(TAG, "安装APK apkPath = $apkPath")
        // 先判断手机是否有root权限
        if (hasRootPermission()) {
            DebugUtil.warnOut(TAG, "有root权限, 使用静默安装实现")
            // 有root权限，使用静默安装实现
            silentInstall(
                packageName,
                launcherActivity,
                apkPath,
                object : OnInstallResultListener {
                    override fun succeed() {
                        DebugUtil.warnOut(TAG, "静默安装成功")
                        onInstallResultListener?.succeed()
                    }

                    override fun failed() {
                        DebugUtil.warnOut(TAG, "静默安装失败，使用通用安装")
                        standardInstall(
                            context,
                            apkPath,
                            onInstallResultListener
                        )
                    }
                })
        } else {
            DebugUtil.warnOut(TAG, "没有root权限, 使用通用安装")
            standardInstall(context, apkPath, onInstallResultListener)
        }
    }

    /**
     * 描述: 卸载
     */
    fun uninstall(packageName: String, context: Context): Boolean {
        DebugUtil.warnOut(TAG, "卸载APK packageName = $packageName")
        return if (hasRootPermission()) {
            DebugUtil.warnOut(TAG, "有root权限, 使用静默卸载实现")
            // 有root权限，利用静默卸载实现
            silentUninstall(packageName)
        } else {
            DebugUtil.warnOut(TAG, "没有root权限, 使用通用卸载")
            val packageURI = "package:$packageName".toUri()
            val uninstallIntent = Intent(Intent.ACTION_DELETE, packageURI)
            uninstallIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            context.startActivity(uninstallIntent)
            true
        }
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 私有方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 标准安装
     *
     * 需要注意在Manifest中添加权限
     *
     * <uses-permission
     *     android:name="android.permission.INSTALL_PACKAGES"
     *     tools:ignore="ProtectedPermissions" />
     * <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
     *
     *
     * @param context                 上下文
     * @param apkPath                 APK文件路径
     * @param onInstallResultListener 相关回调
     */
    fun standardInstall(
        context: Context,
        apkPath: String,
        onInstallResultListener: OnInstallResultListener?
    ) {
        DebugUtil.warnOut(TAG, "标准Intent安装")
        // 没有root权限，利用意图进行安装
        val file = File(apkPath)
        if (!file.exists()) {
            DebugUtil.warnOut(TAG, "文件不存在，安装失败")
            onInstallResultListener?.failed()
            return
        }
        if (!file.isFile) {
            DebugUtil.warnOut(TAG, "路径不是一个完整的文件，安装失败")
            onInstallResultListener?.failed()
            return
        }
        // 由于没有在Activity环境下启动Activity,设置下面的标签
        val intent = Intent(Intent.ACTION_VIEW)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        //8.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            DebugUtil.warnOut(TAG, "8.0以上需要判断是否有安装未知应用权限")
            val hasInstallPermission = context.packageManager.canRequestPackageInstalls()
            if (!hasInstallPermission) {
                DebugUtil.warnOut(
                    TAG,
                    "没有安装未知应用权限，跳转到设置页面让用户开启权限"
                )
                val intent2 = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
                intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                context.startActivity(intent2)
                threadFactory.newThread {
                    Thread.sleep(500)
                    while (true) {
                        if (!isBackgroundRunning()) {
                            break
                        }
                    }
                    DebugUtil.warnOut(TAG, "用户已经从设置页面返回，重新检查是否有安装未知应用权限")
                    if (context.packageManager.canRequestPackageInstalls()) {
                        DebugUtil.warnOut(
                            TAG,
                            "用户已经开启安装未知应用权限，继续执行安装"
                        )
                        handler.post {
                            standardInstall(
                                context,
                                apkPath,
                                onInstallResultListener
                            )
                        }
                    } else {
                        DebugUtil.warnOut(TAG, "用户没有开启安装未知应用权限，停止安装，返回安装失败")
                        handler.post {
                            onInstallResultListener?.failed()
                        }
                    }

                }.start()
                return
            }
            val apkUri = FileProviderUtil.getUriFromFile(context, File(apkPath))
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
        }
        //7.0
        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            DebugUtil.warnOut(TAG, "7.0以下,使用FileProvider将文件转换成content://Uri形式进行安装")
            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致  参数3  共享的文件
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            val apkUri = FileProviderUtil.getUriFromFile(context, File(apkPath))
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
        } else {
            DebugUtil.warnOut(TAG, "7.0以下,直接进行安装")
            intent.setDataAndType(
                Uri.fromFile(File(apkPath)),
                "application/vnd.android.package-archive"
            )
        }
        context.startActivity(intent)
        onInstallResultListener?.succeed()
    }

    /**
     * 判断当前应用是否有安装未知应用权限
     *
     * @return 是否有安装未知应用权限
     */
    fun hasInstallPermission(): Boolean {
        val context = AutoInitProvider.context
        if (context == null) {
            DebugUtil.warnOut(TAG, "context is null")
            return false
        }
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.packageManager.canRequestPackageInstalls()
        } else {
            return true
        }
    }

    /**
     * 跳转到安装未知应用权限设置界面
     */
    fun toInstallPermissionSetting() {
        val context = AutoInitProvider.context
        if (context == null) {
            DebugUtil.warnOut(TAG, "context is null")
            return
        }
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            DebugUtil.warnOut(TAG, "sdk 版本小于26，无需跳转到设置界面")
            return
        }
        val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    }

    /**
     * 静默卸载
     */
    fun silentUninstall(packageName: String): Boolean {
        DebugUtil.warnOut(TAG, "root 静默卸载 packageName = $packageName")
        val printWriter: PrintWriter
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec("su")
            DebugUtil.warnOut(TAG, "执行命令: su")
            printWriter = PrintWriter(process.outputStream)
            printWriter.println("LD_LIBRARY_PATH=/vendor/lib:/system/lib ")
            DebugUtil.warnOut(TAG, "执行命令: LD_LIBRARY_PATH=/vendor/lib:/system/lib ")
            printWriter.println("pm uninstall $packageName")
            DebugUtil.warnOut(TAG, "执行命令: pm uninstall $packageName")
            printWriter.flush()
            printWriter.close()
            DebugUtil.warnOut(TAG, "命令发送完成，等待命令执行完成")
            val value = process.waitFor()
            DebugUtil.warnOut(TAG, "命令执行完成，返回值 = $value")
            return returnResult(value)
        } catch (e: Exception) {
            e.printStackTrace()
            DebugUtil.warnOut(TAG, "命令执行失败, 异常信息 = ${e.message}")
        } finally {
            process?.destroy()
        }
        return false
    }

    /**
     * 静默安装
     */
    fun <T : Activity> silentInstall(
        packageName: String,
        launcherActivity: Class<T>,
        apkPath: String,
        onInstallResultListener: OnInstallResultListener?
    ) {
        DebugUtil.warnOut(
            TAG,
            "静默安装 packageName = $packageName launcherActivity = ${launcherActivity.name} apkPath = $apkPath"
        )
        val file = File(apkPath)
        if (!file.exists()) {
            DebugUtil.warnOut(TAG, "文件不存在, 安装失败")
            onInstallResultListener?.failed()
            return
        }
        if (!file.isFile) {
            DebugUtil.warnOut(TAG, "路径不是一个完整的文件, 安装失败")
            onInstallResultListener?.failed()
            return
        }
        DebugUtil.warnOut(TAG, "root 静默安装")
        threadFactory.newThread {
            val printWriter: PrintWriter
            var process: Process? = null
            var result: Boolean
            try {
                process = Runtime.getRuntime().exec("su")
                DebugUtil.warnOut(TAG, "执行命令: su")
                printWriter = PrintWriter(process.outputStream)
                printWriter.println("chmod 777 $apkPath")
                DebugUtil.warnOut(TAG, "执行命令: chmod 777 $apkPath")
                printWriter.flush()
                printWriter.println("pm install -r $apkPath")
                DebugUtil.warnOut(TAG, "执行命令: pm install -r $apkPath")
                printWriter.flush()
                val command = "am start -n ${packageName}/${
                    launcherActivity.name
                }"
                printWriter.println(command)
                DebugUtil.warnOut(TAG, "执行命令: $command")
                printWriter.flush()
                printWriter.println("exit")
                DebugUtil.warnOut(TAG, "执行命令: exit")
                printWriter.flush()
                printWriter.close()
                DebugUtil.warnOut(TAG, "命令发送完成，等待命令执行完成")
                val value = process.waitFor()
                DebugUtil.warnOut(TAG, "命令执行完成，返回值 = $value")
                result = returnResult(value)
            } catch (e: Exception) {
                e.printStackTrace()
                DebugUtil.warnOut(TAG, "命令执行失败, 异常信息 = ${e.message}")
                result = false
            } finally {
                process?.destroy()
            }

            if (result) {
                DebugUtil.warnOut(TAG, "静默安装结束，命令执行成功")
                onInstallResultListener?.succeed()
            } else {
                DebugUtil.warnOut(TAG, "静默安装结束，命令执行失败")
                onInstallResultListener?.failed()
            }
        }.start()
    }

    /**
     * 判断手机是否有root权限
     */
    fun hasRootPermission(): Boolean {
        DebugUtil.warnOut(TAG, "判断手机是否有root权限")
        val printWriter: PrintWriter
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec("su")
            DebugUtil.warnOut(TAG, "执行命令: su")
            printWriter = PrintWriter(process.outputStream)
            printWriter.println("exit")
            printWriter.flush()
            printWriter.close()
            DebugUtil.warnOut(TAG, "命令发送完成，等待命令执行完成")
            val value = process.waitFor()
            DebugUtil.warnOut(TAG, "命令执行完成，返回值 = $value")
            return returnResult(value)
        } catch (e: Exception) {
            e.printStackTrace()
            DebugUtil.warnOut(TAG, "命令执行失败, 异常信息 = ${e.message}")
        } finally {
            process?.destroy()
        }
        return false
    }

    /**
     * 检查程序是否为后台运行
     */
    fun isBackgroundRunning(): Boolean {
        val context = AutoInitProvider.context
        if (context == null) {
            DebugUtil.warnOut(TAG, "context is null")
            return false
        }
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val runningProcesses = am.runningAppProcesses
        for (processInfo in runningProcesses) {
            if (processInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                for (activeProcess in processInfo.pkgList) {
                    if (activeProcess == context.packageName) {
                        //If your app is the process in foreground, then it's not in running in background
                        DebugUtil.warnOut(TAG, "程序在前台运行")
                        return false
                    }
                }
            }
        }
        DebugUtil.warnOut(TAG, "程序在后台运行")
        return true
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 私有方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    private fun returnResult(value: Int): Boolean {
        // 代表成功
        return when (value) {
            0 -> {
                true
            }

            1 -> { // 失败
                false
            }

            else -> { // 未知情况
                false
            }
        }
    }
}